/*
 *  scoreBoard - Utils.cpp
 *  Copyright 2011 W. Reckman. All rights reserved.
 */
#include <sstream>
#include <math.h>
#include "Utils.h"

const std::string& dirText( DIRECTION dir_ ) {
	static const std::string up( "UP" ), down( "DOWN" ), left( "LEFT" ), right( "RIGHT" ), stop( "STOP" );
	switch ( dir_ ) {
		case D_UP: return up;
		case D_DOWN: return down;
		case D_LEFT: return left;
		case D_RIGHT: return right;
		case D_STOP: default:
			return stop;
	}
}

const std::string& balanceText( BALANCE_KIND bk_ ) {
	static const std::string culture( "CULTURE" ), neutral( "NEUTRAL" ), industry( "INDUSTRY" );
	switch ( bk_ ) {
		case BK_CULTURE: return culture;
		case BK_NEUTRAL: return neutral;
		case BK_INDUSTRY: return industry;
	}
}

const std::string& gameStateText( GAME_STATE gs_ ) {
	static const std::string idle( "IDLE" ), precount( "PRECOUNT" ), playing( "PLAYING" ), endSequence( "END_SEQUENCE" ), end( "END" ), invalid( "INVALID" );
	switch ( gs_ ) {
		case GS_IDLE: return idle;
		case GS_PRECOUNT: return precount;
		case GS_PLAYING: return playing;
		case GS_END_SEQUENCE: return endSequence;
		case GS_END: return end;
		case GS_INVALID: return invalid;
	}
}

const GAME_STATE lookupGameStateText( const string& text_ ) {
	if ( text_ == "idle" ) return GS_IDLE;
	else if ( text_ == "precount" ) return GS_PRECOUNT;
	else if ( text_ == "playing" ) return GS_PLAYING;
	else if ( text_ == "end_sequence" ) return GS_END_SEQUENCE;
	else if ( text_ == "end" ) return GS_END;
	else if ( text_ == "invalid" ) return GS_INVALID;
	else return GS_IDLE; /* NOTE: what else to return? */
}


void drawTtfStringCentered( ofTrueTypeFont& font, const std::string& s, int x, int y ) {
	font.drawString( s, x - font.stringWidth( s ) / 2, y + font.stringHeight( s ) / 2 );
}

bool parseBool( const std::string& value ) {
	if ( value == "true" || value == "True" || value == "TRUE" ||
			value == "1" || value == "t" || value == "T" ) {
		return true;
	} else {
		return false;
	}
}

std::vector<std::string>* tokenize( const std::string& text, char splitChar ) {
	std::stringstream ss( text );
	std::string token;
	
	std::vector<std::string>* result = new std::vector<std::string>();
	
	while ( getline( ss, token, splitChar ) ) {
		result->push_back( token );
	}
	
	return result;
}

float pointDist( const ofPoint& p1, const ofPoint& p2 ) {
	float dx = p2.x - p1.x, dy = p2.y - p1.y;
	return sqrtf( dx * dx + dy * dy );
}

float pointManhattanDist( const ofPoint& p1, const ofPoint& p2 ) {
	float dx = p2.x - p1.x, dy = p2.y - p1.y;
	return dx + dy;
}

//NOTE: the circle is upside down
DIRECTION getVectorOrientation( const ofPoint& p1, const ofPoint& p2 ) {
	ofPoint v = p2 - p1;
	float a = atan2f( v.y, v.x );
	if ( a < 0.0f ) a += 2 * PI;
	
	if ( a >= PI * 1.75f || a < PI * 0.25f ) {
		return D_RIGHT;
	} else if ( a >= PI * 0.25f && a < PI * 0.75f ) {
		return D_DOWN;
	} else if ( a >= PI * 0.75f && a < PI * 1.25f ) {
		return D_LEFT;
	} else if ( a >= PI * 1.25f && a < PI * 1.75f ) {
		return D_UP;
	} else {
		ofLog( OF_LOG_ERROR, "(Utils.h) unknown vector orientation angle (%f)", a );
	}
}

//NOTE: adapted from http://stackoverflow.com/questions/401847/circle-rectangle-collision-detection-intersection/402010#402010
bool circleIntersectsWith( const ofPoint& cPos_, float cRad_, const ofRectangle& rect_ ) {
	float rhw = rect_.width / 2, rhh = rect_.height / 2;
	ofPoint cDist( fabsf( cPos_.x - rect_.x - rhw ), fabsf( cPos_.y - rect_.y - rhh ) );

	if ( cDist.x > rhw + cRad_ ) { return false; }
	if ( cDist.y > rhh + cRad_ ) { return false; }

	if ( cDist.x <= rhw ) { return true; } 
	if ( cDist.y <= rhh ) { return true; }

	float cornerDistanceSq = ( cDist.x - rhw ) * ( cDist.x - rhw ) + ( cDist.y - rhh ) * ( cDist.y - rhh );

	return ( cornerDistanceSq <= cRad_ * cRad_ );
}

const string& getOscGameStateName( GAME_STATE state_ ) {
	//GS_IDLE, GS_PRECOUNT, GS_PLAYING, GS_END_SEQUENCE, GS_END
	static const string stateNames[] = {
		"idle", "precount", "playing", "end_sequence", "end"
	};
	
	return stateNames[state_];
}
